package com.zto.security.web.aspect;

import com.alibaba.fastjson.JSON;
import com.zto.security.dto.AddLogDto;
import com.zto.security.validate.Log;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import springfox.documentation.spring.web.json.Json;

import java.lang.reflect.Method;

/**
 * Created by xingyuchao@zto.cn on 2017-12-06.
 */
@Aspect
@Component
@Slf4j
@SuppressWarnings("unchecked")
public class SystemLogAspect {


    /**
     * @Description: 定义一个方法，声明切入点表达式，该方法不需要其他代码
     * 只记录增删改
     */
    @Pointcut("execution(* com.zto.security.web.controller..*add*(..)) || execution(* com.zto.security.web.controller..*delete*(..)) || execution(* com.zto.security.web.controller..*update*(..))")
    public void declareJoinPointExpression(){}


    /**
     * @Description: 后置通知：在目标方法执行后执行(无论执行目标方法过程中是否发生异常都会执行)，执行的通知
     */

    @After("declareJoinPointExpression()")
    public void afterMethod(JoinPoint joinPoint){
        System.out.println("This is 后置通知");
        String params = "";
        if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {
            for ( int i = 0; i < joinPoint.getArgs().length; i++) {
                params += JSON.toJSON(joinPoint.getArgs()[i]) + ";";
            }
        }

        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            System.out.println(targetName + "==="+ methodName);
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            String operationType = "";
            String operationName = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length && method.getAnnotation(Log.class) != null) {
                        operationType = method.getAnnotation(Log.class).operationType();
                        operationName = method.getAnnotation(Log.class).operationName();
                        break;
                    }
                }
            }

            AddLogDto addLogDto = new AddLogDto();
            addLogDto.setLevel("info");
            addLogDto.setOperation(params);
            addLogDto.setUserId(1);
            addLogDto.setUserName("邢宇超");
            addLogDto.setType(operationType);
            addLogDto.setRemark(operationName);
            //自己处理的业务逻辑，入库或写入日志系统...
        } catch (Exception e) {
            //记录本地异常日志，这里发生异常，后者通知不会执行
            log.error("==后置通知异常==");
            log.error("异常信息:{}", e);
        }
    }


    /**
     * @Description: 异常通知：在目标方法出现异常时会执行的代码   可以访问到异常对象，切可以指定在出现特定异常时再执行通知代码
     */
    @AfterThrowing(value="declareJoinPointExpression()",throwing="e")
    public void afterThrowing(JoinPoint joinPoint,Exception e){
        System.out.println("异常通知");
        String params = "";
        if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {
            for ( int i = 0; i < joinPoint.getArgs().length; i++) {
                params += JSON.toJSON(joinPoint.getArgs()[i]) + ";";
            }
        }
        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            String operationType = "";
            String operationName = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length && method.getAnnotation(Log.class) != null) {
                        operationType = method.getAnnotation(Log.class).operationType();
                        operationName = method.getAnnotation(Log.class).operationName();
                        break;
                    }
                }
            }

            AddLogDto dto = new AddLogDto();
            dto.setLevel("error");
            dto.setOperation(params);
            dto.setUserId(1);
            dto.setUserName("邢宇超");
            dto.setType(operationType);
            dto.setRemark(operationName);

        }  catch (Exception ex) {
            //记录本地异常日志
            log.error("==异常通知异常==");
            log.error("异常信息:{}", ex);
        }
          /*==========记录本地异常日志==========*/
        log.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e, params);

    }

}